import random
import re

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.views import View
from django_redis import get_redis_connection  # 根据django配置项配置获取一个redis的链接对象

from .libs.captcha.captcha import captcha
# from .libs.yuntongxun.ccp_sms import CCP

from meiduo_mall.utils.logger import logger
from celery_tasks.sms.tasks import ccp_send_sms_code

# import logging
# logger = logging.getLogger('django')


class SmsCodeView(View):
    """短信验证码接口"""

    def get(self, request, mobile):

        # 3. 创建连接到redis对象
        conn = get_redis_connection('verify_code')

        # 从redis数据库中获取存入的数据
        send_flag = conn.get(f'send_flag_{mobile}')

        # 然后判断该数据是否存在, 因为上面的数据只存储60s,
        # 所以如果该数据存在, 则意味着, 不超过60s, 直接返回.
        if send_flag:
            return JsonResponse({'code': 400, 'message': '发送短信过于频繁'}, status=400, json_dumps_params={'ensure_ascii': False})

        # 1. 接受参数
        image_code_clint = request.GET.get('image_code')
        uuid = request.GET.get('image_code_id')

        # 2. 校验参数
        if not all((image_code_clint, uuid)):
            return JsonResponse({'code': 400, 'message': '缺少必要参数'}, status=400, json_dumps_params={'ensure_ascii': False})

        # 2.2、约束校验
        if not re.match(r'^[a-zA-Z0-9]{4}$', image_code_clint):
            return JsonResponse({'code': 400, 'message': '图形验证码格式有误'}, status=400, json_dumps_params={'ensure_ascii': False})
        if not re.match(r'^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$', uuid):
            return JsonResponse({'code': 400, 'message': 'uuid有误！'}, status=400, json_dumps_params={'ensure_ascii': False})

        # 4. 提取图形验证码
        image_code_server = conn.get(f'img_{uuid}')
        if not image_code_server:
            # 图像验证码过期或不存在
            return JsonResponse({'code': 400, 'message': '图形验证码失效'}, status=400, json_dumps_params={'ensure_ascii': False})

        # 5. 删除图形验证码
        try:
            conn.delete(f'img_{uuid}')
        except Exception as e:
            logger.error(e)

        # 6. 对比图形验证码
        # bytes转字符串
        image_code_server = image_code_server.decode()

        # 转小写后比较
        if image_code_server.lower() != image_code_clint.lower():
            return JsonResponse({'code': 400, 'message': '输入的图形验证码有误'}, status=400, json_dumps_params={'ensure_ascii': False})

        # 7. 生成6位数短信验证码
        sms_code = '%06d' % random.randint(0, 999999)
        logger.info(sms_code)

        # 8. 保存短信验证码
        # 调用SDK，发送短信
        # CCP().send_template_sms(mobile, [sms_code, 5], 1)
        # print('短信验证码：', sms_code)

        # TODO：以异步的方式发送短信：发布任务
        ccp_send_sms_code.delay(mobile, sms_code)

        # 短信验证码有效期：单位： 300秒
        # conn.setex(f'sms_{mobile}', 300, sms_code)

        # 往redis中存入数据, key值和value值随意指定, 但是时间必须为60s
        # 例如这里key:value为:  send_flag_mobile:1  时间为 60
        # conn.setex(f'send_flag_{mobile}', 60, 1)

        # TODO： 优化，使用redis的pipeline功能，把多条redis命令批量执行
        # （1）获取pipeline对象
        p = conn.pipeline()

        # （2）调用Pipeline对象的方法，把指令加入执行队列中：加入队列，未执行
        p.setex(f'sms_{mobile}', 300, sms_code)
        p.setex(f'send_flag_{mobile}', 60, 1)

        # （3）批量执行：真正发生网络通信
        p.execute()

        # 9. 响应结果
        return JsonResponse({'code': 0, 'message': 'ok'}, json_dumps_params={'ensure_ascii': False})


class ImgCodeView(View):
    """图片验证码接口"""

    def get(self, request, uuid):
        # 1. 提取参数
        # 2. 校验参数
        # 3. 业务数据处理：使用captcha生成图片验证码，写入redis、响应图片数据
        # 3.1 调用captcha生成图片和验证码
        text, image = captcha.generate_captcha()

        # 3.2 把验证码写入redis
        # 格式：:"img_<uuid>:text"
        conn = get_redis_connection('verify_code')
        conn.setex(f'img_{uuid}', 300, text)

        # 4. 构建响应
        return HttpResponse(
            image,  # 图片数据，做为响应体数据
            content_type='image/jpeg'
        )
